﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

namespace Plugin1
{
    public partial class Page2 : Page
    {
        private bool canResize = true;
        Point lastPoint;//移动时最后点坐标
        ResizeDirection _curResizeDirection = ResizeDirection.None;

        public double VerticalOffset = 0;
        public double HorizontalOffset = 0;
        UIElement _resizeElement = null;
        FrameworkElement _targetElement = null;


        public Page2()
        {
            InitializeComponent();
            //_resizeElement = ResizeRDCorner;
            //_targetElement = gridToResize;
            //_curResizeDirection = ResizeDirection.ResizeRDCorner;
            //ResizeRDCorner.MouseLeftButtonDown += Resize_MouseLeftButtonDown;

        }

        // 当用户导航到此页面时执行。
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        #region 大小调整
        private void Resize_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

            if (double.IsNaN(_targetElement.ActualWidth) || double.IsNaN(_targetElement.ActualHeight) || !canResize)
                return;

            _resizeElement.CaptureMouse();

            lastPoint = e.GetPosition(_targetElement.Parent as UIElement);

            Application.Current.RootVisual.MouseMove += Resize_MouseMove;
            Application.Current.RootVisual.MouseLeftButtonUp += Resize_MouseLeftButtonUp;
            Application.Current.RootVisual.MouseLeave += Resize_MouseLeave;
            e.Handled = true;
        }
        private bool isAdjusted = false;
        private void Resize_MouseMove(object sender, MouseEventArgs e)
        {
            Point p2 = e.GetPosition(_targetElement.Parent as UIElement);
            System.Diagnostics.Debug.WriteLine(p2);

            if (double.IsNaN(_targetElement.Width))
                _targetElement.Width = _targetElement.ActualWidth;

            if (double.IsNaN(_targetElement.Height))
                _targetElement.Height = _targetElement.ActualHeight;

            if (!isAdjusted && _targetElement.Parent is Grid)
            {
                AdjustWhenGrid();
                isAdjusted = true;
            }
            if (_curResizeDirection == ResizeDirection.ResizeRight || _curResizeDirection == ResizeDirection.ResizeRDCorner || _curResizeDirection == ResizeDirection.ResizeRTCorner)
            {
                ResizebyRight(p2);
            }

            if (_curResizeDirection == ResizeDirection.ResizeLeft || _curResizeDirection == ResizeDirection.ResizeLTCorner || _curResizeDirection == ResizeDirection.ResizeLDCorner)
            {
                ResizebyLeft(p2);
            }

            if (_curResizeDirection == ResizeDirection.ResizeRDCorner || _curResizeDirection == ResizeDirection.ResizeBottom || _curResizeDirection == ResizeDirection.ResizeLDCorner)
            {
                ResizebyBottom(p2);
            }

            if (_curResizeDirection == ResizeDirection.ResizeLTCorner || _curResizeDirection == ResizeDirection.ResizeTop || _curResizeDirection == ResizeDirection.ResizeRTCorner)
            {
                ResizebyTop(p2);
            }

            lastPoint = p2;

        }

        private void AdjustWhenGrid()
        {
            Grid grid = _targetElement.Parent as Grid;
            int col = Grid.GetColumn(_targetElement);
            int row = Grid.GetRow(_targetElement);
            double left = _targetElement.Margin.Left, right = _targetElement.Margin.Right, top = _targetElement.Margin.Top, bottom = _targetElement.Margin.Bottom;
            for (int i = 0; i < col; i++)
            {
                left += grid.ColumnDefinitions[i].ActualWidth;
            }
            for (int i = col + 1; i < grid.ColumnDefinitions.Count; i++)
            {
                right += grid.ColumnDefinitions[i].ActualWidth;
            }
            for (int i = 0; i < row; i++)
            {
                top += grid.RowDefinitions[i].ActualHeight;
            }
            for (int i = row + 1; i < grid.RowDefinitions.Count; i++)
            {
                bottom += grid.RowDefinitions[i].ActualHeight;
            }

            if (Math.Abs(this.HorizontalOffset) > 0)
            {
                if (_targetElement.HorizontalAlignment == HorizontalAlignment.Stretch || _targetElement.HorizontalAlignment == HorizontalAlignment.Center)
                {
                    left = ((_targetElement.Parent as FrameworkElement).ActualWidth - _targetElement.Width + left - right) / 2;
                    right = 0;
                    _targetElement.HorizontalAlignment = HorizontalAlignment.Left;
                }
            }
            if (_targetElement.HorizontalAlignment == HorizontalAlignment.Left)
            {
                left += this.HorizontalOffset;
                right = 0;
            }
            else if (_targetElement.HorizontalAlignment == HorizontalAlignment.Right)
            {
                left = 0;
                right -= this.HorizontalOffset;
            }
            if (Math.Abs(this.VerticalOffset) > 0)
            {
                if (_targetElement.VerticalAlignment == VerticalAlignment.Stretch || _targetElement.VerticalAlignment == VerticalAlignment.Center)
                {
                    top = ((_targetElement.Parent as FrameworkElement).ActualHeight - _targetElement.Height + top - bottom) / 2;
                    bottom = 0;
                    _targetElement.VerticalAlignment = VerticalAlignment.Top;
                }
            }
            if (_targetElement.VerticalAlignment == VerticalAlignment.Top)
            {
                top += this.VerticalOffset;
                bottom = 0;
            }
            else if (_targetElement.VerticalAlignment == VerticalAlignment.Bottom)
            {
                top = 0;
                bottom -= this.VerticalOffset;
            }
            _targetElement.Margin = new Thickness(left, top, right, bottom);
            this.VerticalOffset = 0;
            this.HorizontalOffset = 0;
            Grid.SetRow(_targetElement, 0);
            Grid.SetColumn(_targetElement, 0);
            Grid.SetColumnSpan(_targetElement, (_targetElement.Parent as Grid).ColumnDefinitions.Count + 1);
            Grid.SetRowSpan(_targetElement, (_targetElement.Parent as Grid).RowDefinitions.Count + 1);
            Canvas.SetZIndex(_targetElement, 10);
        }

        private void ResizebyLeft(Point p2)
        {
            double xoffset = p2.X - lastPoint.X;

            if (p2.X < 3 || (xoffset < 0 && _targetElement.Width + 5 >= (_targetElement.Parent as FrameworkElement).ActualWidth))
                return;

            if (_targetElement.HorizontalAlignment != HorizontalAlignment.Right)
            {
                double right = 0.0;
                if (_targetElement.HorizontalAlignment == HorizontalAlignment.Stretch || _targetElement.HorizontalAlignment == HorizontalAlignment.Center)
                    right = ((_targetElement.Parent as FrameworkElement).ActualWidth - _targetElement.Width + _targetElement.Margin.Right - _targetElement.Margin.Left) / 2 - this.HorizontalOffset;
                else
                    right = (_targetElement.Parent as FrameworkElement).ActualWidth - _targetElement.Width - _targetElement.Margin.Left - this.HorizontalOffset;

                _targetElement.Margin = new Thickness(0, _targetElement.Margin.Top, right, _targetElement.Margin.Bottom);
                this.HorizontalOffset = 0;
                _targetElement.HorizontalAlignment = HorizontalAlignment.Right;
            }

            System.Diagnostics.Debug.WriteLine(xoffset);
            if (_targetElement.Width - xoffset >= _targetElement.MinWidth)
            {
                _targetElement.Width -= xoffset;

                if (_targetElement.Margin.Right - this.HorizontalOffset < 5)
                {
                    _targetElement.Margin = new Thickness(_targetElement.Margin.Left, _targetElement.Margin.Top, _targetElement.Margin.Right - this.HorizontalOffset, _targetElement.Margin.Bottom);
                    this.HorizontalOffset = 0;
                }
                if (_targetElement.Width + 5 > (_targetElement.Parent as FrameworkElement).ActualWidth)
                    _targetElement.Width = (_targetElement.Parent as FrameworkElement).ActualWidth - 5;

                System.Diagnostics.Debug.WriteLine(_targetElement.Width);
                System.Diagnostics.Debug.WriteLine(this.HorizontalOffset);
            }

        }

        private void ResizebyRight(Point p2)
        {
            double xoffset = p2.X - lastPoint.X;

            if (p2.X + 3 > (_targetElement.Parent as FrameworkElement).ActualWidth || (xoffset > 0 && _targetElement.Width + 5 >= (_targetElement.Parent as FrameworkElement).ActualWidth))
                return;

            if (_targetElement.HorizontalAlignment != HorizontalAlignment.Left)
            {
                double left = 0.0;
                if (_targetElement.HorizontalAlignment == HorizontalAlignment.Stretch || _targetElement.HorizontalAlignment == HorizontalAlignment.Center)
                    left = ((_targetElement.Parent as FrameworkElement).ActualWidth - _targetElement.Width + _targetElement.Margin.Left - _targetElement.Margin.Right) / 2 + this.HorizontalOffset;
                else
                    left = (_targetElement.Parent as FrameworkElement).ActualWidth - _targetElement.Width - _targetElement.Margin.Right + this.HorizontalOffset;
                _targetElement.Margin = new Thickness(left, _targetElement.Margin.Top, 0, _targetElement.Margin.Bottom);
                this.HorizontalOffset = 0;
                _targetElement.HorizontalAlignment = HorizontalAlignment.Left;
            }

            System.Diagnostics.Debug.WriteLine(xoffset);
            if (_targetElement.Width + xoffset >= _targetElement.MinWidth)
            {
                _targetElement.Width += xoffset;

                if (_targetElement.Margin.Left + this.HorizontalOffset < 5)
                {
                    _targetElement.Margin = new Thickness(_targetElement.Margin.Left + this.HorizontalOffset, _targetElement.Margin.Top, _targetElement.Margin.Right, _targetElement.Margin.Bottom);
                    this.HorizontalOffset = 0;
                }
                if (_targetElement.Width + 5 > (_targetElement.Parent as FrameworkElement).ActualWidth)
                    _targetElement.Width = (_targetElement.Parent as FrameworkElement).ActualWidth - 5;

                System.Diagnostics.Debug.WriteLine(_targetElement.Width);
                System.Diagnostics.Debug.WriteLine(this.HorizontalOffset);
            }

        }

        private void ResizebyTop(Point p2)
        {
            double yoffset = p2.Y - lastPoint.Y;

            if (p2.Y < 3 || (yoffset < 0 && _targetElement.Height + 5 >= (_targetElement.Parent as FrameworkElement).ActualHeight))
                return;
            if (_targetElement.VerticalAlignment != VerticalAlignment.Bottom)
            {
                double bottom = 0.0;
                if (_targetElement.VerticalAlignment == VerticalAlignment.Stretch || _targetElement.VerticalAlignment == VerticalAlignment.Center)
                    bottom = ((_targetElement.Parent as FrameworkElement).ActualHeight - _targetElement.Height + _targetElement.Margin.Bottom - _targetElement.Margin.Top) / 2 - this.VerticalOffset;
                else
                    bottom = (_targetElement.Parent as FrameworkElement).ActualHeight - _targetElement.Height - _targetElement.Margin.Top - this.VerticalOffset;

                _targetElement.Margin = new Thickness(_targetElement.Margin.Left, 0, _targetElement.Margin.Right, bottom);
                this.VerticalOffset = 0;
                _targetElement.VerticalAlignment = VerticalAlignment.Bottom;
            }

            if (_targetElement.Height - yoffset >= _targetElement.MinHeight)
            {
                _targetElement.Height -= yoffset;

                if (_targetElement.Margin.Top - this.VerticalOffset < 5)
                {
                    _targetElement.Margin = new Thickness(_targetElement.Margin.Left, _targetElement.Margin.Top, _targetElement.Margin.Right, _targetElement.Margin.Bottom - this.VerticalOffset);
                    this.VerticalOffset = 0;
                }
                if (_targetElement.Height + 5 > (_targetElement.Parent as FrameworkElement).ActualHeight)
                    _targetElement.Height = (_targetElement.Parent as FrameworkElement).ActualHeight - 5;

            }
        }

        private void ResizebyBottom(Point p2)
        {
            double yoffset = p2.Y - lastPoint.Y;

            if (p2.Y + 3 > (_targetElement.Parent as FrameworkElement).ActualHeight || (yoffset > 0 && _targetElement.Height + 5 >= (_targetElement.Parent as FrameworkElement).ActualHeight))
                return;
            if (_targetElement.VerticalAlignment != VerticalAlignment.Top)
            {
                double top = 0.0;
                if (_targetElement.VerticalAlignment == VerticalAlignment.Stretch || _targetElement.VerticalAlignment == VerticalAlignment.Center)
                    top = ((_targetElement.Parent as FrameworkElement).ActualHeight - _targetElement.Height + _targetElement.Margin.Top - _targetElement.Margin.Bottom) / 2 + this.VerticalOffset;
                else
                    top = (_targetElement.Parent as FrameworkElement).ActualHeight - _targetElement.Height - _targetElement.Margin.Bottom + this.VerticalOffset;

                _targetElement.Margin = new Thickness(_targetElement.Margin.Left, top, _targetElement.Margin.Right, 0);
                this.VerticalOffset = 0;
                _targetElement.VerticalAlignment = VerticalAlignment.Top;
            }

            if (_targetElement.Height + yoffset >= _targetElement.MinHeight)
            {
                _targetElement.Height += yoffset;

                if (_targetElement.Margin.Top + this.VerticalOffset < 5)
                {
                    _targetElement.Margin = new Thickness(_targetElement.Margin.Left, _targetElement.Margin.Top + this.VerticalOffset, _targetElement.Margin.Right, _targetElement.Margin.Bottom);
                    this.VerticalOffset = 0;
                }
                if (_targetElement.Height + 5 > (_targetElement.Parent as FrameworkElement).ActualHeight)
                    _targetElement.Height = (_targetElement.Parent as FrameworkElement).ActualHeight - 5;

            }
        }

        private void Resize_MouseLeave(object sender, MouseEventArgs e)
        {
            _resizeElement.ReleaseMouseCapture();

            StopResize();
        }
        private void Resize_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _resizeElement.ReleaseMouseCapture();

            StopResize();
        }

        private void StopResize()
        {
            Application.Current.RootVisual.MouseMove -= Resize_MouseMove;
            Application.Current.RootVisual.MouseLeftButtonUp -= Resize_MouseLeftButtonUp;
            Application.Current.RootVisual.MouseLeave -= Resize_MouseLeave;
        }

        #endregion

    }

    public enum ResizeDirection
    {
        None,
        ResizeRDCorner,
        ResizeRTCorner,
        ResizeBottom,
        ResizeRight,
        ResizeLTCorner,
        ResizeLDCorner,
        ResizeLeft,
        ResizeTop
    }
}